package cn.chiship.framework.business.biz.cashier.controller;

import cn.chiship.framework.business.biz.cashier.pojo.dto.NormalPayDto;
import cn.chiship.framework.business.biz.cashier.pojo.dto.RefundDto;
import cn.chiship.framework.business.biz.cashier.pojo.dto.PrepayDto;
import cn.chiship.framework.business.biz.cashier.pojo.dto.WithdrawalApplicationDto;
import cn.chiship.framework.business.biz.cashier.service.PayService;
import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.framework.common.enums.BusinessTypeEnum;
import cn.chiship.sdk.cache.service.UserCacheService;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.annotation.NoParamsSign;
import cn.chiship.sdk.core.annotation.NoVerificationAppIdAndKey;
import cn.chiship.sdk.core.annotation.NoVerificationProjectId;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.util.http.ResponseUtil;
import cn.chiship.sdk.core.util.ip.IpUtils;
import cn.chiship.sdk.framework.util.ServletUtil;
import cn.chiship.sdk.pay.core.enums.TradeTypeEnum;
import cn.chiship.sdk.pay.core.util.WxPayV3HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lijian
 */
@RestController
@RequestMapping("/pay")
@NoParamsSign
@Api(tags = "支付接口")
public class PayController {

    private static final Logger LOGGER = LoggerFactory.getLogger(PayController.class);

    @Resource
    private UserCacheService userCacheService;

    @Resource
    private PayService payService;

    @ApiOperation(value = "根据订单号查询订单状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单号", required = true, dataTypeClass = String.class, paramType = "query")
    })
    @GetMapping(value = "/orderStatusByOrderId")
    public ResponseEntity<BaseResult> getOrderStatusByOrderId(@RequestParam(value = "orderId") String orderId) {
        return new ResponseEntity(payService.getOrderStatusByOrderId(orderId), HttpStatus.OK);
    }

    @ApiOperation(value = "二维码支付生成")
    @ApiImplicitParams({})
    @PostMapping(value = "/generatePayQrCode")
    public ResponseEntity<BaseResult> generatePayQrCode(HttpServletRequest request, @Valid @RequestBody NormalPayDto normalPayDto) {
        return new ResponseEntity(payService.normalPay(TradeTypeEnum.QR_CODE, normalPayDto, IpUtils.getIpAddr(request)), HttpStatus.OK);
    }

    @ApiOperation(value = "H5支付")
    @ApiImplicitParams({})
    @PostMapping(value = "/h5Pay")
    public ResponseEntity<BaseResult> h5Pay(HttpServletRequest request, @Valid @RequestBody NormalPayDto normalPayDto) {
        return new ResponseEntity(payService.normalPay(TradeTypeEnum.H5, normalPayDto, IpUtils.getIpAddr(request)), HttpStatus.OK);
    }

    @ApiOperation(value = "预支付生成")
    @ApiImplicitParams({})
    @PostMapping(value = "/prepay")
    public ResponseEntity<BaseResult> prepay(HttpServletRequest request, @Valid @RequestBody PrepayDto prepayDto) {
        return new ResponseEntity(payService.prepay(prepayDto, IpUtils.getIpAddr(request)), HttpStatus.OK);
    }

    @ApiOperation(value = "退款")
    @ApiImplicitParams({})
    @PostMapping(value = "/refund")
    public ResponseEntity<BaseResult> refund(@Valid @RequestBody RefundDto refundDto) {
        CacheUserVO userVO = userCacheService.getUser();
        return new ResponseEntity(payService.refund(refundDto, userVO), HttpStatus.OK);
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "提现申请")
    @ApiOperation(value = "提现申请")
    @PostMapping(value = "withdrawal")
    public ResponseEntity<BaseResult> withdrawalApplication(@RequestBody @Valid WithdrawalApplicationDto withdrawalApplicationDto) {
        CacheUserVO userVO = userCacheService.getUser();
        return new ResponseEntity(payService.withdrawal(withdrawalApplicationDto, userVO), HttpStatus.OK);
    }

    @ApiOperation(value = "订单电子对账")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "channelPayWay", value = "支付通道", required = true, dataTypeClass = String.class, paramType = "query")
    })
    @GetMapping(value = "/reconciliation/order")
    public ResponseEntity<BaseResult> reconciliationOrder(@RequestParam(value = "orderNo") String orderNo,
                                                          @RequestParam(value = "channelPayWay") String channelPayWay) {
        return new ResponseEntity(payService.reconciliationOrder(orderNo, channelPayWay), HttpStatus.OK);
    }

    @ApiOperation(value = "退款申请电子对账")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "refundNo", value = "退款单号", required = true, dataTypeClass = String.class, paramType = "query")
    })
    @GetMapping(value = "/reconciliation/refund")
    public ResponseEntity<BaseResult> reconciliationRefund(@RequestParam(value = "refundNo") String refundNo) {
        return new ResponseEntity(payService.reconciliationRefund(refundNo), HttpStatus.OK);
    }

    @ApiOperation(value = "微信支付成功后的回调接口")
    @PostMapping("/wxV3/payNotify/{tradeType}")
    @NoVerificationProjectId
    @NoVerificationAppIdAndKey
    @ApiIgnore
    public void wxV3Notify(@PathVariable("tradeType") String tradeType, HttpServletRequest request, HttpServletResponse response) throws IOException {
        /**
         * https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/payment-notice.html
         *
         * 解密后
         *
         * { "code": 200, "data": { "transaction_id": "4200002172202406033801817523",
         * "amount": { "payer_total": 1, "total": 1, "currency": "CNY", "payer_currency":
         * "CNY" }, "mchid": "1669877516", "out_trade_no": "20240603546100002",
         * "trade_state": "SUCCESS", "bank_type": "OTHERS", "appid": "wx45e464fcb2bc28c3",
         * "trade_state_desc": "支付成功", "trade_type": "NATIVE", "attach": "",
         * "success_time": "2024-06-03T11:01:07+08:00", "payer": { "openid":
         * "oeVbo4hVr4nEP54PR9N3jALaKD6s" } }, "message": "操作成功", "success": true }
         */
        LOGGER.info("===============微信支付回调成功==============");
        BaseResult baseResult = WxPayV3HttpUtil.getInstance().config().getCallbackData(request);
        LOGGER.info("===============微信支付回调成功回调参数：==============");
        LOGGER.info(JSON.toJSONString(baseResult));
        payService.dealWxPayNotify(tradeType, baseResult);
        Map<String, String> msg = new HashMap<>(8);
        msg.put("code", "SUCCESS");
        ResponseUtil.writeJson(response, JSON.toJSONString(msg));
    }

    @ApiOperation(value = "微信转账成功后的回调接口")
    @PostMapping("/wxV3/transferNotify")
    @NoVerificationProjectId
    @NoVerificationAppIdAndKey
    @ApiIgnore
    public void wxV3TransferNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /**
         * https://pay.weixin.qq.com/docs/merchant/apis/batch-transfer-to-balance/transfer-batch-callback-notice.html
         */
        LOGGER.info("===============微信转账回调成功==============");
        BaseResult baseResult = WxPayV3HttpUtil.getInstance().config().getCallbackData(request);
        LOGGER.info("===============微信转账回调成功回调参数：==============");
        LOGGER.info(JSON.toJSONString(baseResult));
        payService.dealWxTransferNotify(baseResult);

        Map<String, String> msg = new HashMap<>(8);
        msg.put("code", "SUCCESS");
        ResponseUtil.writeJson(response, JSONObject.toJSONString(msg));
    }

    @ApiOperation(value = "微信退款成功后的回调接口")
    @PostMapping("/wxV3/refundNotify")
    @NoVerificationProjectId
    @NoVerificationAppIdAndKey
    @ApiIgnore
    public void wxV3RefundNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /**
         * https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
         *
         * 解密后
         *
         * { "code": 200, "data": { "transaction_id": "4200002160202406044018045440",
         * "amount": { "payer_total": 50, "total": 50, "payer_refund": 1, "refund": 1 },
         * "mchid": "1669877516", "out_trade_no": "20240604141300019", "refund_status":
         * "SUCCESS", "out_refund_no": "957894059804319744", "success_time":
         * "2024-06-04T16:55:39+08:00", "user_received_account": "支付用户零钱", "refund_id":
         * "50302709602024060494506332869" }, "message": "操作成功", "success": true }
         */
        LOGGER.info("===============微信退款回调成功==============");
        BaseResult baseResult = WxPayV3HttpUtil.getInstance().config().getCallbackData(request);
        LOGGER.info("===============微信支退款回调成功回调参数：==============");
        LOGGER.info(JSON.toJSONString(baseResult));
        payService.dealWxRefundNotify(baseResult);

        Map<String, String> msg = new HashMap<>(8);
        msg.put("code", "SUCCESS");
        ResponseUtil.writeJson(response, JSON.toJSONString(msg));
    }

    @ApiOperation(value = "支付宝支付成功后的回调接口")
    @PostMapping("/ali/payNotify/{tradeType}")
    @NoVerificationProjectId
    @NoVerificationAppIdAndKey
    @ApiIgnore
    public void aliPayNotify(@PathVariable("tradeType") String tradeType, HttpServletResponse response) {
        /**
         * https://opendocs.alipay.com/open/194/103296
         */
        /**
         * { "gmt_create": "2024-06-02 22:49:39", "charset": "UTF-8", "seller_email":
         * "services@chiship.cn", "subject": "账号充值", "sign":
         * "LAzM2qhkD8oWO8gGhUNSw99Hn2u8TlIsDTLfIR0cnc3dFmU79MRPvjimcWUDzMGzYzwHX9oQsQjZvqaOVHsdpmbGVnDeaYln3a2DswymvcC01b7n8LSOJ4nsIOgghiLRA7Y7bGyklnX9imU76yVMl0qKq+kBFgMEfhNf8mNUekGWoZ3rLaFKTMMHET4hYrADwGWFEC8wflmXfvX/4W7BOdn5ko2M4Z3jqI6bUlnG4hT1myabsRuW+V5lX3L7wn0B8+wObR/VfzqEpMR6X0OTmDVZd+AV0TYP/S2Q2a3SpjXAw9+Xx7COhwoHsJXMMiWqyj7xQIBFotrXCw1CHj/4GA==",
         * "buyer_id": "2088702563173626", "body": "账号充值", "invoice_amount": "0.01",
         * "notify_id": "2024060201222224946073621483074146", "fund_bill_list":
         * "[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]", "notify_type":
         * "trade_status_sync", "trade_status": "TRADE_SUCCESS", "receipt_amount": "0.01",
         * "buyer_pay_amount": "0.01", "app_id": "2018081661057690", "sign_type": "RSA2",
         * "seller_id": "2088231390225430", "gmt_payment": "2024-06-02 22:49:46",
         * "notify_time": "2024-06-02 22:49:49", "version": "1.0", "out_trade_no":
         * "20240602834100024", "total_amount": "0.01", "trade_no":
         * "2024060222001473621446226919", "auth_app_id": "2018081661057690",
         * "buyer_logon_id": "183****3321", "point_amount": "0.00" }
         */
        try {
            LOGGER.info("===============支付宝支付Post方式回调成功==============");
            Map<String, Object> dataMap = ServletUtil.getParameterValues();
            LOGGER.info("===============支付宝支付Post方式回调成功回调参数：==============");
            LOGGER.info(JSON.toJSONString(dataMap));
            payService.dealAliPayNotify(tradeType, dataMap, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "支付宝退款成功的回调接口")
    @PostMapping("/ali/refundNotify")
    @NoVerificationProjectId
    @NoVerificationAppIdAndKey
    @ApiIgnore
    public void aliRefundNotify(HttpServletResponse response) {
        /**
         * https://opendocs.alipay.com/open/194/103296 暂时没用到
         */
        try {
            LOGGER.info("===============支付宝退款回调成功==============");
            Map<String, Object> dataMap = ServletUtil.getParameterValues();
            LOGGER.info("===============支付宝退款回调成功回调参数：==============");
            LOGGER.info(JSON.toJSONString(dataMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
